home *** CD-ROM | disk | FTP | other *** search
- /*
- * HashTable abstract class
- *
- * Hash-based object association structure.
- *
- * Copyright © John Wainwright 1988
- *
- * SuperClasses :
- *
- * Instance Vars :
- * table
- * size
- * hashType
- * Class Vars :
- *
- * Methods :
- * new s t - creates a hashtable of size & type
- * get k - gets the keyed value
- * bind k v - create a binding
- * softBind k v - create a binding only if not there
- * push k v - push v onto the keyed list
- * getBinding k - return the binding keyed by k
- * sequence - setup sequence
- * next - next key in sequence
- * nextBinding - next binding in sequence
- * dispose
- * Class Methods :
- *
- */
-
- #include "oic.h"
- #include "generics.h"
- #include "names.h"
-
- class HashTable; /* the HashTable class */
-
- #define TABLE_SIZE 255
-
- struct HashTable_i /* HashTable instance structure */
- {
- object *table; /* array of bindings */
- int size; /* table size */
- int hashType; /* hashing technique */
- int seqCursor; /* cursor used for sequencing */
- };
- typedef struct HashTable_i HashTable_i;
-
- /* -------------------- HashTable Instance methods ------------------- */
-
- method object
- _new(self, h, ha)
- object self;
- register HashTable_i *h;
- register struct { int size, type; } *ha;
- {
- /* the following should be fixed to make it the next largest prime */
- h->size = ((ha->size + TABLE_SIZE - 1) / TABLE_SIZE) * TABLE_SIZE;
-
- h->table = (object *)scalloc(h->size * sizeof(object *));
- h->hashType = ha->type;
-
- return self;
- }
-
- method object
- _get(self, h, key)
- object self;
- register HashTable_i *h;
- register object *key;
- {
- register object *b;
-
- b = h->table + (int)hashOf(*key) % h->size;
- for (; *b != NULL && !isKey(*b, *key); b++)
- if (b >= h->table + h->size)
- b = h->table;
- return (*b == NULL) ? NULL : valueOf(*b);
- }
-
- method object
- _getBinding(self, h, key)
- object self;
- register HashTable_i *h;
- register object *key;
- {
- register object *b;
-
- b = h->table + (int)hashOf(*key) % h->size;
- for (; *b != NULL && !isKey(*b, *key); b++)
- if (b >= h->table + h->size)
- b = h->table;
- return *b;
- }
-
- method object
- _bind(self, h, ha)
- object self;
- register HashTable_i *h;
- register struct { object key, value; } *ha;
- {
- register object *b;
- register int i;
-
- b = h->table + (int)hashOf(ha->key) % h->size;
- for (i = 0; *b != NULL && !isKey(*b, ha->key) && i < h->size; b++, i++)
- if (b >= h->table + h->size)
- b = h->table;
-
- if (i == h->size)
- return bind(enlarge(self), ha->key, ha->value);
- else
- {
- if (*b == NULL)
- *b = New(Binding, ha->key, ha->value);
- else
- set(*b, ha->value);
- return *b;
- }
- }
-
- method object
- _softBind(self, h, ha)
- object self;
- register HashTable_i *h;
- register struct { object key, value; } *ha;
- {
- register object *b;
- register int i;
-
- b = h->table + (int)hashOf(ha->key) % h->size;
- for (i = 0; *b != NULL && !isKey(*b, ha->key) && i < h->size; b++, i++)
- if (b >= h->table + h->size)
- b = h->table;
-
- if (i == h->size)
- return softBind(enlarge(self), ha->key, ha->value);
- else
- {
- if (*b == NULL)
- *b = New(Binding, ha->key, ha->value);
- return *b;
- }
- }
-
- method object
- _sequence(self, h) /* reset sequence start */
- object self;
- register HashTable_i *h;
- {
- h->seqCursor = 0;
-
- return self;
- }
-
- method object
- _next(self, h) /* next key from sequence */
- object self;
- register HashTable_i *h;
- {
- register object binding;
-
- while (h->seqCursor < h->size && (binding = h->table[h->seqCursor]) == NULL)
- h->seqCursor++;
- if (h->seqCursor++ < h->size)
- return keyOf(binding);
- else
- return NULL;
- }
-
- method object
- _dispose(self, h)
- object self;
- register HashTable_i *h;
- {
- free(h->table);
- Super(self);
- }
-
- /* ------------------- Init the HashTable class ---------------------- */
-
- InitHashTableClass()
- {
- HashTable = NewClass(sizeof(HashTable_i), 0, "HashTable", END);
- AddMethods(HashTable,
- newGeneric, _new,
- getGeneric, _get,
- bindGeneric, _bind,
- softBindGeneric, _softBind,
- getBindingGeneric, _getBinding,
- nextGeneric, _next,
- sequenceGeneric, _sequence,
- disposeGeneric, _dispose,
- END);
- }
-
-